package com.nowcoder.community.controller;

import com.nowcoder.community.annotation.LoginRequire;
import com.nowcoder.community.config.CommunityConfig;
import com.nowcoder.community.controller.exception.PageNotFoundException;
import com.nowcoder.community.entity.*;
import com.nowcoder.community.service.FollowService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.service.MessageService;
import com.nowcoder.community.service.UserService;
import com.nowcoder.community.util.CommunityUtils;
import com.nowcoder.community.util.HostHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Controller
@RequestMapping("user")
public class UserController {
    @Autowired
    CommunityConfig appConfig;

    @Autowired
    HostHolder hostHolder;

    @Autowired
    UserService userService;

    @Autowired
    MessageService messageService;

    @Autowired
    LikeService likeService;

    @Autowired
    FollowService followService;

    @GetMapping("profile/{userId}")
    public String profile(Model model, @PathVariable int userId) throws PageNotFoundException {
        User user = userService.findUserById(userId);
        if (user == null) {
            throw new PageNotFoundException();
        }
        model.addAttribute("targetUser", user);
        model.addAttribute("likeCount", likeService.countUserLike(userId));
        model.addAttribute("isFollow", false);
        if (hostHolder.getUser() != null) {
            model.addAttribute("isFollow", followService.isFollow(hostHolder.getUser().getId(), userId));
        }
        model.addAttribute("followCount", followService.countFollow(userId));
        model.addAttribute("followerCount", followService.countFollower(userId));
        return "/site/profile";
    }

    @LoginRequire
    @GetMapping("letter")
    public String letter(Model model, Page page) {
        page.setLimit(5);
        page.setRows(messageService.countConversations(hostHolder.getUser().getId()));
        List<UserConversation> conversations;
        if (page.getRows() > page.getOffset()) {
            conversations = messageService.findConversations(hostHolder.getUser().getId(), page);
        } else {
            conversations = new ArrayList<>();
        }

        model.addAttribute("conversations",
                conversations);
        // set target user;
        for (UserConversation conversation : conversations) {
            int targetUserId = conversation.getMessage().getFromId();
            if (targetUserId == hostHolder.getUser().getId()) {
                targetUserId = conversation.getMessage().getToId();
            }
            conversation.setTargetUser(userService.findUserById(targetUserId));
        }
        return "/site/letter";
    }

    @LoginRequire
    @GetMapping("letter/detail/{conversationId}")
    public ModelAndView letterDetail(@PathVariable String conversationId, Page page) throws PageNotFoundException {
        page.setLimit(5);
        return userService.letterDetail(conversationId, page);
    }

    @LoginRequire
    @GetMapping("notice")
    public String notice(Model model, Page page) {
        page.setLimit(5);
        page.setRows(messageService.countSystemConversations(hostHolder.getUser().getId()));
        List<SystemConversation> conversations;
        if (page.getRows() > page.getOffset()) {
            conversations = messageService.findSystemConversations(hostHolder.getUser().getId(), page);
        } else {
            conversations = new ArrayList<>();
        }
        // set target user;
        for (SystemConversation conversation : conversations) {
            int targetUserId = conversation.getTargetUserId();
            conversation.setTargetUser(userService.findUserById(targetUserId));
        }

        model.addAttribute("conversations",
                conversations);
        return "/site/notice";
    }

    @LoginRequire
    @GetMapping("setting")
    public String setting() {
        return "/site/setting";
    }

    @LoginRequire
    @PostMapping("setting/upload")
    public String uploadHeader(MultipartFile headerImage, Model model){
        if (headerImage != null) {
            String filename = headerImage.getOriginalFilename();
            if (filename != null) {
                String suffix = CommunityUtils.getFilenameSuffix(filename);
                filename = CommunityUtils.generateUUID() + suffix;
                File dest = new File(appConfig.getUploadPath() + "/" + filename);

                try {
                    headerImage.transferTo(dest);
                } catch (IOException e) {
                    String msg;
                    log.error(msg = "头像图片保存失败: " + e.getMessage());
                    throw new RuntimeException(msg, e);
                }
                User user = hostHolder.getUser();
                String headerUrl = appConfig.getPathDomain() + "/user/header/" + filename;
                userService.updateHeaderUrl(user.getId(), headerUrl);
                return "redirect:/user/setting";
            }
        }

        model.addAttribute("uploadMsg", "参数错误!");
        return "/site/setting";
    }

    @LoginRequire
    @PostMapping("setting/password")
    public String updatePassword(Model model, String oldPassword, String newPassword) {
        User user = hostHolder.getUser();
        if (!Objects.equals(CommunityUtils.encodePassword(oldPassword, user.getSalt()), user.getPassword())) {
            model.addAttribute("oldPasswordMsg", "初始密码不正确!");
            return "/site/setting";
        }
        userService.updatePassword(user.getId(), CommunityUtils.encodePassword(newPassword, user.getSalt()));
        model.addAttribute("targetUrl", "/user/setting");
        model.addAttribute("msg", "密码修改成功!");
        return "/site/operate-result";
    }

    @GetMapping("header/{filename}")
    public void getHeaderImage(@PathVariable String filename, HttpServletResponse resp) {

        String filepath = appConfig.getUploadPath() + "/" + filename;
        String suffix = CommunityUtils.getFilenameSuffix(filename);
        resp.setContentType("image/" + suffix);
        try (
                FileInputStream fis = new FileInputStream(filepath);
                OutputStream os = resp.getOutputStream()
        ){
            byte[] buffer = new byte[1024];
            for (int i=fis.read(buffer); i != -1;) {
                os.write(buffer, 0, i);
                i = fis.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
